package monster.flight.admin.manager.imp.admin;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import monster.comm.util.BeanHelp;
import monster.comm.util.DateUtil;
import monster.comm.util.MyBatisBatchInsertSupport;
import monster.comm.util.Tool;
import monster.flight.admin.manager.service.admin.Flight_infoService;
import monster.flight.comm.entity.dao.Flight_change_infoDAO;
import monster.flight.comm.entity.dao.Flight_infoDAO;
import monster.flight.comm.entity.dao.T2001DAO;
import monster.flight.comm.entity.vo.Flight_change_info;
import monster.flight.comm.entity.vo.Flight_info;
import monster.flight.comm.entity.vo.Flight_info_All;

import org.apache.commons.beanutils.BeanUtilsBean;

/**
 * 创建信息=============
 * 类名: monster.flight.admin.manager.imp.xtgl.Flight_infoServiceImp
 * 类作用描述: 此类负责航班的相关服务
 * 创建人： wanghong 
 * 创建时间： 2013-1-11 下午01:15:50
 * 修改信息1=============
 * 修改类型:    //1.修改bug 2.业务变化修改
 * 修改描述: 
 * 修改人：  
 * 修改时间:
 * 
 */

public class Flight_infoServiceImp implements Flight_infoService{
	//locks map  不同的时间加不同的锁，避免所有操作都争用一个锁
    public final static Map<String, Object> locks = new ConcurrentHashMap<String, Object>();  
    private Flight_infoDAO flight_infoDAO;
    private Flight_change_infoDAO flight_change_infoDAO;
    private T2001DAO t2001DAO;//远程表
    private MyBatisBatchInsertSupport insertSupport;
    /**
     * 1 查询远程表t2001
     * 2 查询本地表flight_info
     * 3 对比 前两步结果：
     * a 本地不存在的新增，b 本地存在的但远程没有变化的不操作 ，
     * c 本地存在的远程有变化的修改flight_info表，新增flight_change_info表
     */
    @Override
    public void fill(String flight_date) throws Exception{    	
    	if(flight_date==null||flight_date.equals("")){
    		flight_date = DateUtil.getDate("yyyy-MM-dd");
    	}   	
    	getObject(flight_date);
    	//查询远程数据获得传入时间航班信息
    	List<Flight_info> flight_infoRemote = selectRemoteInfo(flight_date);
    	if(flight_infoRemote.size()==0){
    		return;
    	}
    	synchronized(getObjectOnly(flight_date)){
    		List<Flight_info> flight_infoClient = selectClientInfo(flight_date);
    	
	    	if(flight_infoClient.size()==0){//第一次填充数据
	    		//只新增航班信息
		    	insert(flight_infoRemote);
	    	}else{//不是第一次填充数据
		    	List<Flight_info> flight_infoRemote_clone = BeanHelp.deepCopyBean(flight_infoRemote);
		    	//比较得到本地不存在的航班信息
		    	flight_infoRemote.removeAll(flight_infoClient);
		    	//新增航班信息和航班改变信息（即临时增加的航班）
		    	insertInfoAndInsertChangeInfo(flight_infoRemote);
		    	//比较得到本地存在的远程航班信息
		    	flight_infoRemote_clone.retainAll(flight_infoClient);
		    	//更改航班信息，插入改变信息
		    	updateInfoAndInsertChangeInfo(flight_infoRemote_clone,flight_infoClient);
	    	}
    	}
    }    
	
	@Override
	public List<Flight_info>  selectClientInfo(String flight_date)throws Exception{
		List<Flight_info> flight_info = null;
	    flight_info = flight_infoDAO.selectInfo(flight_date);
		if(flight_info==null){
			flight_info = new ArrayList<Flight_info>(0);
		}
		return flight_info;
		
	} 
	@Override
	public  int selectClientInfoCount(String flight_date)throws Exception{
		synchronized(getObject(flight_date)){
			return flight_infoDAO.selectInfoCount(flight_date);
		}
	}
	
	private List<Flight_info> selectRemoteInfo(String flight_date)throws Exception{
		Date date= DateUtil.convertStringToDate("yyyy-MM-dd", flight_date);
		List<Flight_info> flight_info = t2001DAO.selectRemoteInfo(date);
		if(flight_info==null){
			flight_info = new ArrayList<Flight_info>(0);
		}
		return flight_info;
	}
	/**
	 * 
     * 根据前台传入日期查询远程数据库，查得数据后与flight_info表比较，当flight_info表没有记录时 将记录插入 flight_info表
     * 使用批量插入方法
	 * @param flight_infos
	 * @throws Exception
	 */
	private  void insert(List<Flight_info> flight_infos) throws Exception {
		Tool.NullException(flight_infos, "flight_info 为null");
		insertSupport.batchInsert("monster.flight.comm.entity.dao.Flight_infoDAO.insert", flight_infos);
	}
	/**
	 * 轮询远程数据库，查得数据后与flight_info表比较，当本地有记录且本地和远程行数不相等时
     * 新增flight_info表并向flight_change_info插入改变后数据
	 * @param flight_infos
	 * @throws Exception
	 */
	private  void insertInfoAndInsertChangeInfo(List<Flight_info> flight_infos) throws Exception {
		Tool.NullException(flight_infos, "flight_info 为null");
		insertSupport.batchInsert("monster.flight.comm.entity.dao.Flight_infoDAO.insert", flight_infos);
	}
	/**
	 * 轮询远程数据库，查得数据后与flight_info表比较，当记录改变时修改相应的flight_info表并向flight_change_info插入改变后数据
	 * @param flight_infos_remote
	 * @param flight_infos_client
	 * @throws Exception
	 */
	private  void updateInfoAndInsertChangeInfo(List<Flight_info> flight_infos_remote,List<Flight_info> flight_infos_client)
			throws Exception {
		BeanUtilsBean bue = new BeanUtilsBean();
		List<Flight_info_All> flight_infos_r = new ArrayList<Flight_info_All>(flight_infos_remote.size());
		for(int i=0;i<flight_infos_remote.size();i++){
			flight_infos_r.add(i, new Flight_info_All());
			bue.copyProperties(flight_infos_r.get(i), flight_infos_remote.get(i));
		}
		List<Flight_info_All> flight_infos_c = new ArrayList<Flight_info_All>(flight_infos_client.size());
		for(int i=0;i<flight_infos_client.size();i++){
			flight_infos_c.add(i, new Flight_info_All());
			bue.copyProperties(flight_infos_c.get(i), flight_infos_client.get(i));
		}
		//除去没有改变的航班信息
		flight_infos_r.removeAll(flight_infos_c);
		List<Flight_info> flight_infos = new ArrayList<Flight_info>(flight_infos_r.size());
		for(int i=0;i<flight_infos_r.size();i++){
			flight_infos.add(i, new Flight_info());
			bue.copyProperties(flight_infos.get(i), flight_infos_r.get(i));
		}		
		//修改航班信息
		insertSupport.batchInsert("monster.flight.comm.entity.dao.Flight_infoDAO.update", flight_infos);
		//新增航班改变信息
		List<Flight_change_info> flight_change_infos = new ArrayList<Flight_change_info>(flight_infos_r.size());
		String create_time = DateUtil.getDateTime();
		for(int i=0;i<flight_infos_r.size();i++){
			flight_change_infos.add(i, new Flight_change_info());
			bue.copyProperties(flight_change_infos.get(i), flight_infos_r.get(i));
			flight_change_infos.get(i).setCreate_time(create_time);
			flight_change_infos.get(i).setIs_close_alert("0");
			flight_change_infos.get(i).setClose_alert_time("");
		}	
		insertSupport.batchInsert("monster.flight.comm.entity.dao.Flight_change_infoDAO.insert",flight_change_infos);
	}
	public Flight_infoDAO getFlight_infoDAO() {
		return flight_infoDAO;
	}

	public void setFlight_infoDAO(Flight_infoDAO flight_infoDAO) {
		this.flight_infoDAO = flight_infoDAO;
	}

	
    
	

	public Flight_change_infoDAO getFlight_change_infoDAO() {
		return flight_change_infoDAO;
	}

	public void setFlight_change_infoDAO(Flight_change_infoDAO flight_change_infoDAO) {
		this.flight_change_infoDAO = flight_change_infoDAO;
	}
	public T2001DAO getT2001DAO() {
		return t2001DAO;
	}
	public void setT2001DAO(T2001DAO t2001dao) {
		t2001DAO = t2001dao;
	}

	public MyBatisBatchInsertSupport getInsertSupport() {
		return insertSupport;
	}

	public void setInsertSupport(MyBatisBatchInsertSupport insertSupport) {
		this.insertSupport = insertSupport;
	}
   /**
    * 非原子操作的ConcurrentHashMap需加上锁以保证线程安全
    * @param flight_date
    * @return
    */
   private Object getObject(String flight_date){
	   Object obj = null;  
       synchronized(locks){  
           obj = locks.get(flight_date);  
           if(obj == null){  
               obj = new Object();  
               locks.put(flight_date, obj);  
           }  
       }
       return obj;
   }
   /**
    * ConcurrentHashMap 保证原子操作的线程安全
    * @param flight_date
    * @return
    */
   private Object getObjectOnly(String flight_date){
       return locks.get(flight_date);  
   }
	

}
